/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package slicktest.entities.maps;

import java.util.LinkedList;
import java.util.List;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;

import slicktest.entities.Drawable.Drawable;
import slicktest.entities.GameEntity;
import slicktest.entities.ImmobileEntity.ImmobileEntity;
import slicktest.entities.ImmobileEntity.Terrain;
import slicktest.entities.ImmobileEntity.Tower;

/**
 * @author enrightt
 */
public class GameMap implements Drawable, GameEntity {

    private List<Drawable> drawables;
    private ImmobileEntity[][] terrainGrid;
    private ImmobileEntity[][] towerGrid;
    private int tileWidth;
    private int tileHeight;
    //camera position type stuff. 
    private int camX;
    private int camY;
    //number of rows and columns in this map
    private int rows;
    private int cols;
    //use this for bounding on scroll
    private final int xCenter;
    private final int yCenter;
    private final int buffer;

    public GameMap(int rows, int cols, int tileWidth, int tileHeight, int xCenter, int yCenter, int buffer) {
        drawables = new LinkedList<Drawable>();

        this.rows = rows;
        this.cols = cols;

        terrainGrid = new ImmobileEntity[rows][cols];
        towerGrid = new ImmobileEntity[rows][cols];

        this.tileWidth = tileWidth;
        this.tileHeight = tileHeight;

        this.camX = xCenter;
        this.xCenter = xCenter;

        this.camY = yCenter;
        this.yCenter = yCenter;

        this.buffer = buffer;
    }

    public int getCamX() {
        return camX;
    }

    public int getCamY() {
        return camY;
    }

    //adds terrain to the entityGrid
    public void addTerrain(Terrain t, int xPos, int yPos) {
        drawables.add(t);
        t.setX(xPos * tileWidth);
        t.setY(yPos * tileHeight);
        terrainGrid[xPos][yPos] = t;
    }

    public ImmobileEntity getTerrain(int xPos, int yPos) {
        return terrainGrid[xPos][yPos];
    }

    public void addTower(Tower t, int xPos, int yPos) {
        drawables.add(t);
        System.out.println("before: " + t);
        t.setX(xPos * tileWidth);
        t.setY(yPos * tileHeight);

        boolean[][] footprint = t.getFootprint();
        List<Terrain> terrainEntries = new LinkedList<Terrain>();

        for (int i = 0; i < footprint.length; i++) {
            for (int j = 0; j < footprint[i].length; j++) {
                boolean nextEntry = footprint[i][j];

                if (nextEntry) {
                    Terrain component = (Terrain) terrainGrid[(i + xPos)][(j + yPos)];
                    terrainEntries.add(component);
                    if (towerGrid[(i + xPos)][j + yPos] == null) {
                        towerGrid[(i + xPos)][(j + yPos)] = t;
                        System.out.print("setting " + (i + xPos) + "," + (j + yPos));
                        System.out.println(" to the presented tower");
                    } else {
                        System.out.print("not setting " + (i + xPos) + "," + (j + yPos) + ", already a tower there");
                    }
                }
            }
        }

        t.setStatsFromTerrain(terrainEntries);
        System.out.println("after: " + t);
    }

    public ImmobileEntity getTower(int xPos, int yPos) {
        return towerGrid[xPos][yPos];
    }

    public String getType() {
        return "Composite Game Map";
    }

    public void render(GameContainer gc, Graphics g) throws SlickException {
        g.pushTransform();
        g.translate((gc.getWidth() / 2) - (this.camX), (gc.getHeight() / 2) - (this.camY));
        for (Drawable drawable : drawables) {
            drawable.render(gc, g);
        }
        g.popTransform();
    }

    public void update(GameContainer gc, int delta) throws SlickException {
        Input input = gc.getInput();

        if (input.isKeyDown(input.KEY_LEFT)) {
            if (camX > xCenter) {
                camX = (int) Math.max(camX - (delta * .5), xCenter);
            }

        } else if (input.isKeyDown(input.KEY_RIGHT)) {
            if (camX < (tileWidth * rows) - xCenter) {
                camX = (int) Math.min(camX + (delta * .5), (tileWidth * rows) - xCenter);
            }
        }

        if (input.isKeyDown(input.KEY_UP)) {
            if (camY > yCenter) {
                camY = (int) Math.max(camY - (delta * .5), yCenter);
            }

        } else if (input.isKeyDown(input.KEY_DOWN)) {
            if (camY < (tileHeight * cols) - yCenter) {
                camY = (int) Math.min(camY + (delta * .5), (tileHeight * cols) - yCenter);
            }
        }

        int mouseX = input.getMouseX();
        int mouseY = input.getMouseY();

        if (input.isMouseButtonDown(input.MOUSE_MIDDLE_BUTTON)) {
            if (mouseX < xCenter - (tileWidth * buffer)) {
                if (camX > xCenter) {
                    camX = (int) Math.max(camX - (delta * .5), xCenter);
                }
            } else if (mouseX > xCenter + (tileWidth * buffer)) {
                if (camX < (tileWidth * rows) - xCenter) {
                    camX = (int) Math.min(camX + (delta * .5), (tileWidth * rows) - xCenter);
                }
            }

            if (mouseY < yCenter - (tileHeight * buffer)) {
                if (camY > yCenter) {
                    camY = (int) Math.max(camY - (delta * .5), yCenter);
                }
            } else if (mouseY > yCenter + (tileHeight * buffer)) {
                if (camY < (tileHeight * cols) - yCenter) {
                    camY = (int) Math.min(camY + (delta * .5), (tileHeight * cols) - yCenter);
                }
            }
        }
    }
}
